package main

import (
	"fmt"
	"reflect"
)

type Student struct {
	Name string
	Age  int
}

func (this *Student)PrintName() {
	fmt.Println(this.Name)
}
func (this *Student)GetAge() int {
	return this.Age
}

func main() {
	s := Student{Name:"ldw", Age:30}
	rt := reflect.TypeOf(s)
	if rt.Kind() == reflect.Ptr {
		rt = rt.Elem()
	}
	//类型所在包的路径
	fmt.Println(rt.PkgPath())//main
	fmt.Println(rt.Name(), "共有", rt.NumField(), "个字段")//Student 共有 2 个字段
	for i, j := 0, rt.NumField(); i < j; i++ {
		rtField := rt.Field(i)
		fmt.Println(rtField.Name)
	}
	rt = reflect.PtrTo(rt)//转换为指针类型,否则反射取不到函数
	fmt.Println(rt.Name(), "共有", rt.NumMethod(), "个函数")//Student 共有 2 个函数
	for i, j := 0, rt.NumMethod(); i < j; i++ {
		mt := rt.Method(i)
		fmt.Println(mt.Name)
		numIn := mt.Type.NumIn()
		numOut := mt.Type.NumOut()
		if numIn > 0 {
			fmt.Println("\t共",numIn,"个输入参数")
			for k := 0; k < numIn; k++ {
				in := mt.Type.In(k)
				fmt.Println("\t", in.Name(), "\t", in.Kind())
			}
		}
		if numOut > 0 {
			fmt.Println("\t共",numOut,"个输出参数")
			for k := 0; k < numOut; k++ {
				out := mt.Type.Out(k)
				fmt.Println("\t", out.Name(), "\t", out.Kind())
			}
		}
	}

	rv :=reflect.ValueOf(s)
	if rv.Kind() == reflect.Ptr {
		rv = rv.Elem()
	}
	rvField := rv.FieldByName("Name")
	fmt.Println(rvField.String())

	//SetString，SetBoll，SetInt反射时必须是对指针反射
	rv2 :=reflect.ValueOf(&s)
	if rv2.Kind() == reflect.Ptr {
		rv2 = rv2.Elem()
	}
	rvField2 := rv2.FieldByName("Name")
	fmt.Println(rvField2.String())
	rvField2.SetString("sss")
	fmt.Println(s.Name)

}